﻿using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Claims;
using System.Text;
using CURD.Token;
using EFCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Model;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace CURD.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class TestController : ControllerBase
    {
        public readonly MyDbContext ctx;
        private readonly IOptionsSnapshot<JwtSetting> jwtSettingOpt;

        public TestController(IOptionsSnapshot<JwtSetting> jwtSettingOpt, MyDbContext ctx)
        {
            this.ctx = ctx;
            this.jwtSettingOpt = jwtSettingOpt;
        }



        [HttpGet]
        public IActionResult Login(string username, string password)
        {
            //判断数据库中是否存在这个账号
            if (username == "111" && password == "111")
            {
                //添加信息 后面加密 claim是一个身份类
                List<Claim> claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.NameIdentifier, "1"));
                claims.Add(new Claim(ClaimTypes.Name, username));
                claims.Add(new Claim(ClaimTypes.Role, "admin"));

                //获取配置中存放的密匙和过期时间
                string key = jwtSettingOpt.Value.SecretKey;
                DateTime expire = DateTime.Now.AddSeconds(jwtSettingOpt.Value.Expired);

                ///解析 加密 
                byte[] secBytes = Encoding.UTF8.GetBytes(key);
                var secKey = new SymmetricSecurityKey(secBytes);
                var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature);
                var tokenDescriptor = new JwtSecurityToken(claims: claims, expires: expire, signingCredentials: credentials);
                string jwt = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);

                return Ok(jwt);
            }
            else
            {
                return BadRequest();
            }
        }

        [Authorize]
        [HttpGet]
        public IActionResult TestAuthorization()
        {
            var a = this.User.FindFirst(ClaimTypes.Name);
            return Ok("111" + a.Value);
        }


        [Authorize(Roles = "Admin")]
        [HttpGet]
        public IActionResult GetBooksCount()
        {

            int res = ctx.Books.Count();
            return Ok(res);
        }

        [HttpGet]
        public IActionResult GetBook()
        {

            int res = ctx.Books.Count();
            List<Book> booklist = ctx.Books.ToList();   

            var result = new
            {
                code = 0,
                count = res,
                data = booklist
            };

            return Ok(result);
        }

        [HttpPost]
        public async Task<IActionResult> InsertBook(BookReq book)
        {
            Guid id = Guid.NewGuid();
            Book books = new Book();
            books.Id = id.ToString();
            books.Title = book.Title;
            books.Author = book.Author;
            books.Description = book.Description;
            books.Price = book.Price;

            ctx.Books.Add(books);
            int res = await ctx.SaveChangesAsync();
            return Ok(res);
        }
        [HttpPost]
        public async Task<IActionResult> UpdateBook(BookReq book, string id)
        {
            Book? books = ctx.Books.FirstOrDefault(b => b.Id == id);
            if (books != null)
            {
                books.Title = book.Title;
                books.Author = book.Author;
                books.Description = book.Description;
            }
            int res = await ctx.SaveChangesAsync();
            return Ok(res);
        }


        [HttpPost]
        public async Task<IActionResult> DeleteBook(string id)
        {
            Book book = ctx.Books.FirstOrDefault(b => b.Id == id);
            if (book != null)
            {
                ctx.Remove(book);
                int res = await ctx.SaveChangesAsync();
                return Ok(res);
            }
            return NoContent();
        }

    }
}
